package com.xinqi.modules.third.service.impl;

import com.alibaba.nacos.common.utils.UuidUtils;
import com.aliyun.oss.*;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.xinqi.common.core.constant.Constants;
import com.xinqi.common.core.utils.DateUtils;
import com.xinqi.modules.third.service.ISysOssService;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 文件上传 服务层实现
 *
 * @author dgyu
 */
@Log4j2
@Service
public class SysOssServiceImpl implements ISysOssService {

    @Value("${aliyun.oss.secretAccessKey}")
    private String secretAccessKey;

    @Value("${aliyun.oss.accessKey}")
    private String accessKey;

    /*成都配置*/
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;

    @Value("${aliyun.oss.bucketName}")
    private String bucketName;

    @Value("${aliyun.oss.ossUrl}")
    private String ossUrl;

    @Value("${aliyun.oss.ossUrl2}")
    private String ossUrl2;

    /**
     * 获取阿里云OSS凭证
     */
    @Override
    public Map<String, String> findOssPolicy() {
        String host = "https://" + bucketName + "." + endpoint;
        String format = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDateTime.now());
        String dir = format + "/";
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretAccessKey);
        try {
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            // PostObject请求最大可支持的文件大小为5 GB，即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            Map<String, String> respMap = new LinkedHashMap<String, String>();
            respMap.put("accessid", accessKey);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
            respMap.put("currentTime", String.valueOf(System.currentTimeMillis()));
            return respMap;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ossClient.shutdown();
        }
        return null;
    }

    /**
     * 获取阿里云url在线预览
     */
    @Override
    public String onlinePreview(String url) {

        if (url.contains(Constants.HTTPS)) {
            url = url.replace(ossUrl + "/", "");
        } else {
            url = url.replace(ossUrl2 + "/", "");
        }


        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretAccessKey);
        String fileUrl = "";
        try {
            // 设置样式，样式中包含文档预览参数。
            String style = "imm/previewdoc,copy_1";
            // 指定签名URL过期时间为10分钟。
            Date expiration = new Date(DateUtils.getNowDateTime() + 1000 * 60 * 10);
            GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, url, HttpMethod.GET);
            req.setExpiration(expiration);
            req.setProcess(style);
            URL signedUrl = ossClient.generatePresignedUrl(req);
            fileUrl = signedUrl.toString();
        } catch (OSSException oe) {
        } catch (ClientException ce) {
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return fileUrl;
    }

    /**
     * 下载OSS切片原数据
     */
    @Override
    public String downFile(String ossPath, String targetFolder) {
        if (ossPath.equals(Constants.HTTP)) {
            ossPath.replace(Constants.HTTPS, Constants.HTTP);
        }
        String fileName = ossPath.replace(ossUrl + "/", "");
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretAccessKey);
        String targetFile = targetFolder + File.separator + fileName.substring(fileName.lastIndexOf("/") + 1);
        File file = new File(targetFile);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        ossClient.getObject(new GetObjectRequest(bucketName, fileName), file);
        ossClient.shutdown();
        return targetFile;
    }

    /**
     * 上传本地文件到下载阿里OSS
     */
    @Override
    public List<String> uploadFile(List<String> filePaths, String ossFolderPath) {
        List<String> ossUrls = new ArrayList<>();
        String uuid = UuidUtils.generateUuid().replace("-", "");
        try {
            if (filePaths != null && filePaths.size() > 0) {
                OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretAccessKey);
                for (String path : filePaths) {
                    File file = new File(path);
                    //获取上传文件输入流
                    InputStream inputStream = Files.newInputStream(Paths.get(path));
                    //获取文件名称
                    String fileName = file.getName();
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
                    String datePath = simpleDateFormat.format(new Date());
                    //拼接
                    String targetFileName = datePath + "/" + ossFolderPath + "/" + uuid + "/" + fileName;
                    ossClient.putObject(bucketName, targetFileName, inputStream);
                    ossUrls.add(ossUrl + "/" + targetFileName);
                }
            }
        } catch (Exception e) {
            return null;
        }
        return ossUrls;
    }

    /**
     * 删除阿里OSS文件
     */
    @Override
    public boolean deleteFile(String url) {
        boolean flag = false;
        OSS ossClient = null;
        try {
            // 创建OSSClient实例。
            ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretAccessKey);

            String objectName = null;
            // 填写Object完整路径，完整路径中不能包含Bucket名称。
            if (url.contains(Constants.HTTPS)) {
                objectName = url.replace(ossUrl + "/", "");
            } else {
                objectName = url.replace(ossUrl2 + "/", "");
            }
            // 删除文件或目录。如果要删除目录，目录必须为空。
            ossClient.deleteObject(bucketName, objectName);
            flag = true;
        } catch (OSSException oe) {
            flag = false;
        } catch (ClientException ce) {
            flag = false;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return flag;
    }
}
